/**
 * 
 * The MIT License
 * 
 * Copyright (c) 2008 the original author or authors.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.googlecode.gchartjava;

/**
 * Perusing the <a href="http://groups.google.com/group/google-chart-api">
 * Google Chart API Group</a> reveals that a lot of users and developers are
 * having difficulty transforming or normalizing their data. A common question
 * is "What do I do about negative numbers?". Or "What if my data lies outside
 * the simple or extended encoding range?" The answer to these problems is that
 * users must normalize their data so that they may be rendered in the chart.
 * This class helps users achieve that goal.
 * 
 * @author Julien Chastang (julien.c.chastang at gmail dot com)
 * 
 * @see Data
 */
public class DataUtil {

	/**
	 * Static factory method that will normalize data between the min and max.
	 * If max equals min or max is less than min, no normalization will occur.
	 * 
	 * Note that the min value can be less than the minimum value of the data
	 * and that the max value can be greater than the maximum value of the data.
	 * This scenario is useful when you don't want your plot to span the entire
	 * chart, but you would like the plots to be squeezed in a bit.
	 * 
	 * @param min
	 *            The minimum value in the normalization range.
	 * @param max
	 *            The maximum value in the normalization range.
	 * @param data
	 *            The data
	 * @return A Data object normalized between min and max.
	 * 
	 * @see Data
	 */
	public static Data normalize(final float min, final float max, final float[] data) {
		if (max - min <= 0)
			return newData(data);
		else
			return newData(normalize(data, min, max));
	}
	
	/**
	 * Static factory method that will simply normalize between the minimum and
	 * maximum values in the data.
	 * 
	 * @param data
	 *            Provide a data series that will be normalized by this method.
	 * 
	 * @return A Data object normalized between minimum and maximum in the
	 *         provided data series.
	 *         
	 * @see Data
	 */
	public static Data normalize(final float... data) {
	    float min = Float.MAX_VALUE;
	    float max = Float.MIN_VALUE;
	    for (float f : data) {
	      min = (f < min) ? f : min;
	      max = (f > max) ? f : max;
	    }
		return newData(normalize(data, min, max));
	}

	/**
	 * 
	 */
	private static float[] normalize(final float[] floatArray, final float min, final float max) {
		final float maxDiff = max - min;
		if (maxDiff <= 0)
			return floatArray;
		final float[] normalizedData = new float[floatArray.length];
		for (int j = 0; j < floatArray.length; j++) {
			normalizedData[j] = ((floatArray[j] - min) / maxDiff) * 100;
		}
		return normalizedData;
	}
	
	/**
	 * 
	 */
	private static Data newData(final float... data) {
		return new Data(data);
	}
}
